package com.jdd.modules.parkcar.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.andyczy.java.excel.ExcelUtils;
import com.jdd.common.api.vo.Result;
import com.jdd.common.aspect.annotation.*;
import com.jdd.common.constant.JddConstant;
import com.jdd.common.system.query.QueryGenerator;
import com.jdd.common.system.vo.LoginUser;
import com.jdd.common.util.LoginUserUtils;
import com.jdd.common.util.PlateNoCheckUtil;
import com.jdd.common.util.SnowFlakeUtil;
import com.jdd.common.util.excel.entity.params.ExportParams;
import com.jdd.common.util.excel.web.entity.vo.NormalExcelConstants;
import com.jdd.common.util.excel.web.view.EasypoiSingleExcelView;
import com.jdd.modules.configcartype.entity.ConfigCarType;
import com.jdd.modules.configcartype.service.impl.ConfigCarTypeServiceImpl;
import com.jdd.modules.parkWhiteEdit.entity.ParkWhiteEditList;
import com.jdd.modules.parkWhiteEdit.service.impl.ParkWhiteEditListServiceImpl;
import com.jdd.modules.parkcar.entity.ImportResultMessage;
import com.jdd.modules.parkcar.entity.MonthlyRentalCarInfo;
import com.jdd.modules.parkcar.entity.ParkCarMonthly;
import com.jdd.modules.parkcar.entity.ParkSpace;
import com.jdd.modules.parkcar.service.IParkCarMonthlyService;
import com.jdd.modules.parkcar.service.IParkSpaceService;
import com.jdd.modules.parkcar.util.ParkCarUtil;
import com.jdd.modules.parkcar.vo.ParkCarMonthlyVO;
import com.jdd.modules.parking.entity.ConfigParkInfo;
import com.jdd.modules.parking.service.IConfigParkInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;

/**
 * @Description: 月租车信息
 * @Author: jdd
 * @Date: 2021-05-24
 * @Version: V1.0
 */
@Slf4j
@Api(tags = "月租车信息")
@RestController
@RequestMapping("/parkCar/parkCarMonthly")
public class ParkCarMonthlyController {
    @Resource
    private IParkCarMonthlyService parkCarMonthlyService;
    @Resource
    private ConfigCarTypeServiceImpl configCarTypeService;
    @Resource
    private ExecutorService executorService;
    @Resource
    private IParkSpaceService parkSpaceService;
    @Resource
    private ParkWhiteEditListServiceImpl parkWhiteEditListService;
    private ParkCarUtil parkCarUtil;
    @Resource
    private IConfigParkInfoService configParkInfoService;

    /**
     * 分页列表查询
     *
     * @param parkCarMonthly
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    @AutoLog(value = "月租车信息-分页列表查询")
    @ApiOperation(value = "月租车信息-分页列表查询", notes = "月租车信息-分页列表查询")
    @GetMapping(value = "/list")
    public Result<IPage<ParkCarMonthly>> queryPageList(ParkCarMonthly parkCarMonthly,
                                                       @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                                       @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                                       HttpServletRequest req) throws IllegalAccessException {
        Result<IPage<ParkCarMonthly>> result = new Result<IPage<ParkCarMonthly>>();
        String startTime = req.getParameter("endTime_begin");
        String endTime = req.getParameter("endTime_end");
        QueryWrapper<ParkCarMonthly> queryWrapper = new QueryWrapper<>();
        //时间用大于小于
        if (ObjectUtil.isNotNull(startTime)) {
            queryWrapper.ge("start_time", startTime);
        }
        if (ObjectUtil.isNotNull(endTime)) {
            queryWrapper.le("end_time", endTime);
        }
        //反射得到属性值并加入wrapper
        Class<? extends ParkCarMonthly> carMonthlyClass = parkCarMonthly.getClass();
        Field[] fields = carMonthlyClass.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            //如果是静态或者final就不管
            if (Modifier.isFinal(field.getModifiers()) && Modifier.isStatic(field.getModifiers())) {
                continue;
            }
            Object o = field.get(parkCarMonthly);
            if (ObjectUtil.isNotNull(o)) {
                //车牌是模糊查询的，其他都是等值的，wrapper没法覆盖，所以用的else
                if ("plateNo".equals(field.getName())) {
                    queryWrapper.like("plate_no", parkCarMonthly.getPlateNo());
                } else {
                    TableField tableField = field.getAnnotation(TableField.class);
                    queryWrapper.eq(tableField.value(), field.get(parkCarMonthly));
                }
            }
            field.setAccessible(true);
        }
        Page<ParkCarMonthly> page = new Page<ParkCarMonthly>(pageNo, pageSize);
        queryWrapper.orderByDesc("create_time");
        IPage<ParkCarMonthly> pageList = parkCarMonthlyService.page(page, queryWrapper);
        result.setSuccess(true);
        result.setResult(pageList);
        return result;
    }


    @AutoLog(value = "月租车信息导入-查询用户车场对应的月租车类型列表")
    @ApiOperation(value = "月租车信息导入-查询用户车场对应的月租车类型列表", notes = "月租车信息导入-查询用户车场对应的月租车类型列表")
    @GetMapping(value = "/getMonCarTypeList")
    public Result<List<ConfigCarType>> getMonCarTypeList() {
        Result<List<ConfigCarType>> result = new Result<>();
        LambdaQueryWrapper<ConfigCarType> configCarTypeWrapper = new LambdaQueryWrapper<>();
        configCarTypeWrapper.eq(ConfigCarType::getCarType, "1");
        List<ConfigCarType> carTypeList = configCarTypeService.list(configCarTypeWrapper);
        result.setResult(carTypeList);
        result.setSuccess(true);
        return result;
    }

    /**
     * 白名单-详情-月租车类型
     *
     * @param map
     * @return configCarType
     */

    @AutoLog(value = "白名单-详情-月租车类型")
    @ApiOperation(value = "白名单-详情-月租车类型", notes = "白名单-详情-月租车类型")
    @PostMapping(value = "/carTypeInfo")
    public Result<ConfigCarType> getCarTypeInfo(@RequestBody Map<String, String> map
    ) {
        String carTypeId = map.get("carTypeId");
        Result<ConfigCarType> result = new Result<ConfigCarType>();
        QueryWrapper<ConfigCarType> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", carTypeId);
        ConfigCarType configCarType = configCarTypeService.getOne(queryWrapper);
        result.setResult(configCarType);
        result.setSuccess(true);
        return result;
    }

    /**
     * 添加
     *
     * @param parkCarMonthly
     * @return
     */
    @AutoLog(value = "月租车信息-添加")
    @ApiOperation(value = "月租车信息-添加", notes = "月租车信息-添加")
    @PostMapping(value = "/add")
    @OperationLogDetail(detail = "月租车信息添加", level = LogLevelType.ONE, operationType = OperationType.INSERT, operationUnit = OperationUnit.UNKNOWN)
    public Result<ParkCarMonthly> add(@RequestBody ParkCarMonthly parkCarMonthly) {
        Result<ParkCarMonthly> result = new Result<ParkCarMonthly>();
        try {
            ConfigParkInfo configParkInfo = configParkInfoService.findConfigParkInfoByParkCode();
            if (ObjectUtil.isNull(configParkInfo)) {
                return Result.error(510, "车辆信息配置为空，请检查");
            }
            if (!PlateNoCheckUtil.checkPlateNo(parkCarMonthly.getPlateNo())) {
                // 若格式错误，则返回错误信息
                return Result.error(510, "车牌号错误");
            }
            parkCarMonthly.setParkCode(configParkInfo.getParkCode());
            parkCarMonthly.setParkName(configParkInfo.getParkName());
            parkCarMonthly.setStatus(JddConstant.StatusType.STATUS_Y);
            LambdaQueryWrapper<ParkCarMonthly> carCheckQueryWrapper = new LambdaQueryWrapper<>();
            carCheckQueryWrapper.eq(ParkCarMonthly::getPlateNo, parkCarMonthly.getPlateNo());
            carCheckQueryWrapper.eq(ParkCarMonthly::getParkCode, parkCarMonthly.getParkCode());
            // 查询是否在同一车场下，有相同车牌号的数据
            List<ParkCarMonthly> carList = parkCarMonthlyService.list(carCheckQueryWrapper);
            for (int i = 0; i < carList.size(); i++) {
                if (StringUtils.isBlank(carList.get(i).getParkNumber())) {
                    if (StringUtils.isBlank(parkCarMonthly.getParkNumber())) {
                        return result.error500("该车牌号已添加了一条无车位的月租车信息，请勿重复添加");
                    } else {
                        return result.error500("该车牌号已添加了一条无车位的月租车信息，若要为该车牌号设置车位，请先删除无车位的月租车信息");
                    }
                } else {
                    if (carList.get(i).getParkNumber().equals(parkCarMonthly.getParkNumber())) {
                        return result.error500("请勿添加重复数据");
                    }
                    if (StringUtils.isBlank(parkCarMonthly.getParkNumber())) {
                        return result.error500("该车牌号已添加了一条有车位的月租车信息，若要将该车牌号设置为无车位，请先删除有车位的月租车信息");
                    }
                }
            }
            parkCarMonthlyService.save(parkCarMonthly);
            result.success("添加成功！");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            result.error500("操作失败");
        }
        return result;
    }

    /**
     * 编辑
     *
     * @param parkCarMonthly
     * @return
     */
    @AutoLog(value = "月租车信息-编辑")
    @ApiOperation(value = "月租车信息-编辑", notes = "月租车信息-编辑")
    @PutMapping(value = "/edit")
    @OperationLogDetail(detail = "月租车信息编辑", level = LogLevelType.ONE, operationType = OperationType.UPDATE, operationUnit = OperationUnit.UNKNOWN)
    public Result<ParkCarMonthly> edit(@RequestBody ParkCarMonthly parkCarMonthly) {
        Result<ParkCarMonthly> result = new Result<ParkCarMonthly>();
        // 检测编辑的对象是否在数据库中存在
        ParkCarMonthly parkCarMonthlyEntity = parkCarMonthlyService.getById(parkCarMonthly.getId());
        if (parkCarMonthlyEntity == null) {
            // 如果不存在，则返回错误信息
            result.error500("未找到对应实体");
            return result;
        }
        // 则检测车牌号格式
        if (!PlateNoCheckUtil.checkPlateNo(parkCarMonthly.getPlateNo())) {
            // 若格式错误，则返回错误信息
            return Result.error(510, "车牌号错误");
        }
        LambdaQueryWrapper<ParkCarMonthly> carCheckQueryWrapper = new LambdaQueryWrapper<>();
        carCheckQueryWrapper.eq(ParkCarMonthly::getPlateNo, parkCarMonthly.getPlateNo());
        carCheckQueryWrapper.ne(ParkCarMonthly::getId, parkCarMonthly.getId());
        // 查询是否在同一车场下，有相同车牌号的数据
        List<ParkCarMonthly> carList = parkCarMonthlyService.list(carCheckQueryWrapper);
        for (int i = 0; i < carList.size(); i++) {
            if (StringUtils.isBlank(carList.get(i).getParkNumber())) {
                if (StringUtils.isBlank(parkCarMonthly.getParkNumber())) {
                    return result.error500("该车牌号已添加了一条无车位的月租车信息，请勿重复添加");
                } else {
                    return result.error500("该车牌号已添加了一条无车位的月租车信息，若要为该车牌号设置车位，请先删除无车位的月租车信息");
                }
            } else {
                if (carList.get(i).getParkNumber().equals(parkCarMonthly.getParkNumber())) {
                    return result.error500("请勿添加重复数据");
                }
                if (StringUtils.isBlank(parkCarMonthly.getParkNumber())) {
                    return result.error500("该车牌号已添加了一条有车位的月租车信息，若要将该车牌号设置为无车位，请先删除有车位的月租车信息");
                }
            }
        }
        if (!parkCarMonthly.getEndTime().equals(parkCarMonthlyEntity.getEndTime())) {
            ParkWhiteEditList parkWhiteEditList = getParkWhiteEditList(parkCarMonthly);
            parkWhiteEditList.setLicenseType(1);
            parkWhiteEditList.setUpdateTime(new Date());
            parkWhiteEditList.setEndTime(parkCarMonthly.getEndTime());
            parkWhiteEditList.setBeforeEntTime(parkCarMonthlyEntity.getEndTime());
            parkWhiteEditList.setOptionsType(2);
            try {
                parkWhiteEditListService.save(parkWhiteEditList);
            } catch (Exception e) {
                return result.error500("延期纪录保存失败");
            }

        }
        boolean ok = parkCarMonthlyService.updateById(parkCarMonthly);
        //判断是否是月组车 并且当前到期时间跟原到期时间不同
        if (ok) {
            result.success("修改成功!");
        }
        return result;
    }

    /**
     * 通过id删除
     *
     * @param id
     * @return
     */
    @AutoLog(value = "月租车信息-通过id删除")
    @ApiOperation(value = "月租车信息-通过id删除", notes = "月租车信息-通过id删除")
    @DeleteMapping(value = "/delete")
    @OperationLogDetail(detail = "月租车通过id删除", level = LogLevelType.ONE, operationType = OperationType.DELETE, operationUnit = OperationUnit.UNKNOWN)
    public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
        try {
            parkCarMonthlyService.removeById(id);
        } catch (Exception e) {
            log.error("删除失败", e.getMessage());
            return Result.error("删除失败!");
        }
        return Result.ok("删除成功!");
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @AutoLog(value = "月租车信息-批量删除")
    @ApiOperation(value = "月租车信息-批量删除", notes = "月租车信息-批量删除")
    @DeleteMapping(value = "/deleteBatch")
    @OperationLogDetail(detail = "月租车批量删除", level = LogLevelType.ONE, operationType = OperationType.DELETE, operationUnit = OperationUnit.UNKNOWN)
    public Result<ParkCarMonthly> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
        Result<ParkCarMonthly> result = new Result<ParkCarMonthly>();
        if (ids == null || "".equals(ids.trim())) {
            result.error500("参数不识别！");
        } else {
            this.parkCarMonthlyService.removeByIds(Arrays.asList(ids.split(",")));
            result.success("删除成功!");
        }
        return result;
    }

    /**
     * 通过id查询
     *
     * @param id
     * @return
     */
    @AutoLog(value = "月租车信息-通过id查询")
    @ApiOperation(value = "月租车信息-通过id查询", notes = "月租车信息-通过id查询")
    @GetMapping(value = "/queryById")
    public Result<ParkCarMonthly> queryById(@RequestParam(name = "id", required = true) String id) {
        Result<ParkCarMonthly> result = new Result<ParkCarMonthly>();
        ParkCarMonthly parkCarMonthly = parkCarMonthlyService.getById(id);
        if (parkCarMonthly == null) {
            result.error500("未找到对应实体");
        } else {
            result.setResult(parkCarMonthly);
            result.setSuccess(true);
        }
        return result;
    }

    /**
     * 导出excel
     *
     * @param request
     * @param response
     */
    @RequestMapping(value = "/ParkCarMonthlyExportXls")
    public ModelAndView exportXls(HttpServletRequest request, HttpServletResponse response, ParkCarMonthly parkCarMonthly) {
        // Step.1 组装查询条件
        QueryWrapper<ParkCarMonthly> queryWrapper = QueryGenerator.initQueryWrapper(parkCarMonthly, request.getParameterMap());
        parkCarUtil = new ParkCarUtil();
        // Step.2 AutoPoi 导出Excel
        ModelAndView mv = new ModelAndView(new EasypoiSingleExcelView());
        mv.addObject(NormalExcelConstants.FILE_NAME, "月租车列表");
        mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("月租车列表数据", "导出信息"));
        // 导出文件名称
        // 查询表中数据大小
        int listSize = parkCarMonthlyService.count(queryWrapper);
        // 定义每页数量
        int pageSize = 100;
        // 定义线程列表
        List<CompletableFuture<ModelAndView>> futureList = new ArrayList<>();
        // 循环查询，每次查询一页
        for (int pageNo = 1; pageNo <= listSize / pageSize + 1; pageNo++) {
            int number = pageNo;
            // 开启线程查询
            CompletableFuture<ModelAndView> completableFuture = CompletableFuture.supplyAsync(() -> {
                return parkCarUtil.addDataToModelAndView(new ModelAndView(), parkCarMonthlyService, queryWrapper, number, pageSize);
            }, executorService);
            futureList.add(completableFuture);
        }
        // 等待每个线程结束后
        CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0])).join();
        List<ParkCarMonthly> resultList = new ArrayList<>();
        futureList.forEach(a -> {
            try {
                // 将结果添加到列表中
                resultList.addAll((List<ParkCarMonthly>) a.join().getModel().get(NormalExcelConstants.DATA_LIST));
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        // 将数据添加到Excel文件内
        mv.addObject(NormalExcelConstants.CLASS, ParkCarMonthly.class);
        mv.addObject(NormalExcelConstants.DATA_LIST, resultList);
        return mv;
    }


    /**
     * @param request 文件上传请求
     * @return
     */
    @AutoLog(value = "月租车信息导入-将月租车信息导入数据库")
    @ApiOperation(value = "月租车信息导入-将月租车信息导入数据库", notes = "月租车信息导入-将月租车信息导入数据库")
    @RequestMapping(value = "/importExcel")
    public ModelAndView importExcel1(HttpServletRequest request, ParkCarMonthlyVO vo) throws IOException {
        log.info("----月租车信息导入----");

        LoginUser loginUser = LoginUserUtils.getLoginUser();
        ModelAndView mv = new ModelAndView(new EasypoiSingleExcelView());
        mv.addObject(NormalExcelConstants.FILE_NAME, "月租车信息导入结果");
        mv.addObject(NormalExcelConstants.CLASS, ImportResultMessage.class);
        mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("月租车信息导入结果", "月租车信息导入结果"));
        List<ImportResultMessage> importResultMessageList = new LinkedList<>();
        // 获得上传文件的请求
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        // 从请求中获得上传文件的集合
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        // 遍历文件集合
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            // 获得文件
            MultipartFile file = entity.getValue();
            // 得到文件名
            String fileName = file.getOriginalFilename();
            // 设置Excel文件的标题所在行数
            HashMap<Integer, Integer> hashMapIndex = new HashMap<>(1);
            hashMapIndex.put(1, 3);
            // 设置Excel文件单页名称
            String[] sheetNames = new String[]{"月租车模板"};
            // 获得Excel文件的输入流
            InputStream inputStream = file.getInputStream();
            Workbook book = null;
            try {
                // 获得Excel文件的扩展名
                String extName = fileName.substring(fileName.lastIndexOf('.') + 1);
                if (StringUtils.equals("xls", extName)) {
                    // Excel文件为Excel2003之前的版本
                    book = new HSSFWorkbook(inputStream);
                } else if (StringUtils.equals("xlsx", extName)) {
                    // Excel文件的版本为Excel2007
                    book = new XSSFWorkbook(inputStream);
                } else {
                    log.error("无法识别的Excel文件,请下载模板文件,进行导入!");
                    mv.addObject(NormalExcelConstants.CLASS, ImportResultMessage.class);
                    ImportResultMessage importResultMessage = new ImportResultMessage();
                    importResultMessage.setMessage("无法识别的Excel文件，请下载模板文件，进行导入！");
                    importResultMessageList.add(importResultMessage);
                    mv.addObject(NormalExcelConstants.DATA_LIST, importResultMessageList);
                    return mv;
                }
                // 初始化Excel工具类
                ExcelUtils excelUtils = ExcelUtils.initialization();
                // 设置工具类读取日期数据的格式
                excelUtils.setDateFormatStr("yyyy-MM-dd");
                excelUtils.setExpectDateFormatStr("yyyy-MM-dd");
                // 读取Excel文件
                List<List<LinkedHashMap<String, String>>> list = ExcelUtils.importForExcelData(book, sheetNames, hashMapIndex, null);
                //检测导入Excel文件的大小
                Result<Object> listSizeCheckResult = importListSizeCheck(list, 500);
                //如果检测不成功
                if (listSizeCheckResult.getCode() != 200) {
                    ImportResultMessage importResultMessage = new ImportResultMessage();
                    importResultMessage.setMessage(listSizeCheckResult.getMessage());
                    importResultMessageList.add(importResultMessage);
                    mv.addObject(NormalExcelConstants.DATA_LIST, importResultMessageList);
                    // 返回检测结果
                    return mv;
                }
                List<ParkCarMonthly> parkCarMonthlyList = new ArrayList<>();
                List<ParkCarMonthly> sameParkCarMonthlyList = new ArrayList<>();
                for (List<LinkedHashMap<String, String>> linkedHashMaps : list) {
                    importResultMessageList = getNoSameDataParkCarMonthly(linkedHashMaps, parkCarMonthlyList, sameParkCarMonthlyList, vo);
                }
                List<CompletableFuture<List<ImportResultMessage>>> futureList = new ArrayList<>();
                int pageSize = 100;
                int pageNumber = parkCarMonthlyList.size() / pageSize;
                for (int i = 0; i <= pageNumber; i++) {
                    int index = i;
                    if (index == pageNumber) {
                        CompletableFuture<List<ImportResultMessage>> completableFuture = CompletableFuture.supplyAsync(() -> {
                            return importParkCarMonthlyListByList(parkCarMonthlyList.subList(index * pageSize, parkCarMonthlyList.size()), loginUser);
                        }, executorService);
                        futureList.add(completableFuture);
                    } else {
                        CompletableFuture<List<ImportResultMessage>> completableFuture = CompletableFuture.supplyAsync(() -> {
                            return importParkCarMonthlyListByList(parkCarMonthlyList.subList(index * pageSize, index * pageSize + pageSize), loginUser);
                        }, executorService);
                        futureList.add(completableFuture);
                    }
                }
                // 等待每个线程结束后
                CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0])).join();
                List<ImportResultMessage> resultMessages = importResultMessageList;
                futureList.forEach(a -> {
                    try {
                        // 将结果添加到列表中
                        resultMessages.addAll((List<ImportResultMessage>) a.join());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                });
                importResultMessageList = resultMessages;
            } catch (Exception e) {
                log.error("月租车信息导入", e);
                ImportResultMessage importResultMessage = new ImportResultMessage();
                importResultMessage.setMessage("月租车信息导入失败");
                importResultMessageList.add(importResultMessage);
                mv.addObject(NormalExcelConstants.DATA_LIST, importResultMessageList);
                return mv;
            }
        }
        if (importResultMessageList.size() == 0) {
            ImportResultMessage importResultMessage = new ImportResultMessage();
            importResultMessage.setLocationX("无");
            importResultMessage.setLocationY(0);
            importResultMessage.setPlateNo("无");
            importResultMessage.setMessage("导入成功");
            importResultMessageList.add(importResultMessage);
        }
        mv.addObject(NormalExcelConstants.DATA_LIST, importResultMessageList);
        return mv;
    }


    /**
     * @param request
     * @param response
     * @param map
     * @return
     */
    @AutoLog(value = "月租车信息导入-导出月租车信息模板")
    @ApiOperation(value = "月租车信息导入-导出月租车信息模板", notes = "月租车信息导入-导出月租车信息模板")
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls1(HttpServletRequest request, HttpServletResponse response, Map<String, Object> map) {

        ModelAndView mv = new ModelAndView(new EasypoiSingleExcelView());
        mv.addObject(NormalExcelConstants.FILE_NAME, "月租车信息");
        mv.addObject(NormalExcelConstants.CLASS, MonthlyRentalCarInfo.class);
        mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("月租车信息", "月租车模板"));

        MonthlyRentalCarInfo monthlyRentalCarInfo = new MonthlyRentalCarInfo(null, null, null, null, null, null, null, null, null );
        List<MonthlyRentalCarInfo> list = new LinkedList<>();
        list.add(monthlyRentalCarInfo);
        mv.addObject(NormalExcelConstants.DATA_LIST, list);
        return mv;
    }

    /**
     * 按list批量导入
     *
     * @param list 格式正确的月租车信息
     * @return 导入结果信息
     * @Author liuyaowen
     */
    private List<ImportResultMessage> importParkCarMonthlyListByList(List<ParkCarMonthly> list, LoginUser loginUser) {
        List<ImportResultMessage> importResultMessageList = new ArrayList<>();
        for (ParkCarMonthly parkCarMonthly : list) {
            LambdaQueryWrapper<ParkCarMonthly> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ParkCarMonthly::getParkCode, loginUser.getParkCode());
            queryWrapper.eq(ParkCarMonthly::getParkNumber, parkCarMonthly.getParkNumber());
            // 检测车位是否存在
            List<ParkCarMonthly> checkList = parkCarMonthlyService.list(queryWrapper);
            if (CollectionUtil.isNotEmpty(checkList)) {
                // 如果车位存在，则检测是否存有绑定相同车位的相同车牌号
                List<ParkCarMonthly> sameParkCarMonthly = checkList.stream().filter(monthlyCar -> monthlyCar.getPlateNo().equals(parkCarMonthly.getPlateNo())).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(sameParkCarMonthly)) {
                    // 存在
                    ImportResultMessage message = new ImportResultMessage();
                    message.setPlateNo(parkCarMonthly.getPlateNo());
                    message.setMessage("已存在的数据，重复导入");
                    importResultMessageList.add(message);
                } else {
                    // 不存在，则只新增月租车信息
                    parkCarMonthlyService.save(parkCarMonthly);
                }
            } else {
                // 不存在该车位，则新增车位
                parkCarMonthlyService.save(parkCarMonthly);
                ParkSpace parkSpace = getParkSpace(parkCarMonthly, loginUser);
                parkSpaceService.save(parkSpace);
            }
        }
        return importResultMessageList;
    }

    /**
     * Excel列表中数据格式自检测
     *
     * @param linkedHashMaps 导入的月租车信息列表
     * @param noSameDataList 用于存储的格式正确的，无相同数据的月租车信息
     * @param sameDatalist   用于存储拥有相同数据的月租车信息
     * @return 导入结果信息
     * @Author liuyaowen
     */
    private List<ImportResultMessage> getNoSameDataParkCarMonthly(List<LinkedHashMap<String, String>> linkedHashMaps, List<ParkCarMonthly> noSameDataList, List<ParkCarMonthly> sameDatalist, ParkCarMonthlyVO vo) {
        LoginUser loginUser = LoginUserUtils.getLoginUser();
        String parkCode = loginUser.getParkCode();
        String parkName = loginUser.getParkName();
        Set<String> noSameDataPlantNoList = new HashSet<>();
        Set<String> noSameDataParkNumberList = new HashSet<>();
        List<ImportResultMessage> list = new ArrayList<>();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        for (int index = 0; index < linkedHashMaps.size(); index++) {
            ImportResultMessage message = new ImportResultMessage();
            LinkedHashMap<String, String> linkedHashMap = linkedHashMaps.get(index);
            ParkCarMonthly parkCarMonthly = new ParkCarMonthly();
            if (StringUtils.isBlank(linkedHashMap.get("0")) || !PlateNoCheckUtil.checkPlateNo(linkedHashMap.get("0"))) {
                // 如果车辆的车牌号为空或错误的格式，放弃此数据，立即开始导入一下条数据
                log.error("车牌号格式错误");
                log.error("parkCode:" + parkCode + ",Plant_No" + parkCarMonthly.getPlateNo());
                message.setPlateNo(parkCarMonthly.getPlateNo());
                message.setMessage("车牌号格式错误");
                list.add(message);
                continue;
            } else {
                parkCarMonthly.setPlateNo(linkedHashMap.get("0"));
            }
            if (StringUtils.isBlank(linkedHashMap.get("3"))) {
                // 如果车辆的用户名称为空，放弃此数据，立即开始导入一下条数据
                log.error("月租车客户姓名为空");
                log.error("park_Code:" + parkCode + ",Plant_No：" + parkCarMonthly.getPlateNo());
                message.setPlateNo(parkCarMonthly.getPlateNo());
                message.setMessage("月租车客户姓名为空");
                list.add(message);
                continue;
            } else {
                parkCarMonthly.setUserName(linkedHashMap.get("3"));
            }
            if (StringUtils.isBlank(linkedHashMap.get("4"))) {
                // 如果车辆的手机号为空，放弃此数据，立即开始导入一下条数据
                log.info("月租车客户手机号为空");
                log.info("park_Code:" + parkCode + ",Plant_No" + parkCarMonthly.getPlateNo());
                message.setPlateNo(parkCarMonthly.getPlateNo());
                message.setMessage("客户手机号码为空");
                list.add(message);
                continue;
            } else {
                parkCarMonthly.setMobile(linkedHashMap.get("4"));
            }
            if (StringUtils.isNotBlank(linkedHashMap.get("1"))) {
                try {
                    Calendar calendar = Calendar.getInstance();
                    if (StringUtils.isBlank(vo.getStartTime())) {
                        calendar.setTime(simpleDateFormat.parse(linkedHashMap.get("1")));
                    } else {
                        calendar.setTime(simpleDateFormat.parse(vo.getStartTime()));
                    }
                    calendar.set(Calendar.HOUR_OF_DAY, 0);
                    calendar.set(Calendar.MINUTE, 0);
                    calendar.set(Calendar.SECOND, 0);
                    parkCarMonthly.setStartTime(DateUtil.parse(DateUtil.format(calendar.getTime(), "yyyy-MM-dd HH:mm:ss")));
                } catch (Exception e) {
                    log.info("月租车有效起始时间格式错误");
                    log.info("park_Code:" + parkCode + ",Plant_No" + parkCarMonthly.getPlateNo());
                    message.setPlateNo(parkCarMonthly.getPlateNo());
                    message.setMessage("月租车有效起始时间格式错误");
                    list.add(message);
                    continue;
                }
            } else {
                log.info("月租车有效起始时间为空");
                log.info("park_Code:" + parkCode + ",Plant_No" + parkCarMonthly.getPlateNo());
                message.setPlateNo(parkCarMonthly.getPlateNo());
                message.setMessage("月租车有效起始时间为空");
                list.add(message);
                continue;
            }
            if (StringUtils.isNotBlank(linkedHashMap.get("2"))) {
                try {
                    Calendar calendar = Calendar.getInstance();
                    if (StringUtils.isBlank(vo.getEndTime())) {
                        calendar.setTime(simpleDateFormat.parse(linkedHashMap.get("2")));
                    } else {
                        calendar.setTime(simpleDateFormat.parse(vo.getEndTime()));
                    }
                    calendar.set(Calendar.HOUR_OF_DAY, 23);
                    calendar.set(Calendar.MINUTE, 59);
                    calendar.set(Calendar.SECOND, 59);
                    parkCarMonthly.setEndTime(DateUtil.parse(DateUtil.format(calendar.getTime(), "yyyy-MM-dd HH:mm:ss")));
                } catch (Exception e) {
                    log.info("月租车有效过期时间格式错误");
                    log.info("park_Code:" + parkCode + ",Plant_No" + parkCarMonthly.getPlateNo());
                    message.setPlateNo(parkCarMonthly.getPlateNo());
                    message.setMessage("月租车有效过期时间格式错误");
                    list.add(message);
                    continue;
                }
            } else {
                log.info("月租车有效过期时间为空");
                log.info("park_Code:" + parkCode + ",Plant_No" + parkCarMonthly.getPlateNo());
                message.setPlateNo(parkCarMonthly.getPlateNo());
                message.setMessage("月租车有效过期时间为空");
                list.add(message);
                continue;
            }
            parkCarMonthly.setId(SnowFlakeUtil.getId());
            parkCarMonthly.setParkCode(parkCode);
            parkCarMonthly.setParkName(parkName);
            parkCarMonthly.setParkNumber(linkedHashMap.get("5"));
            parkCarMonthly.setAddress(linkedHashMap.get("6"));
            parkCarMonthly.setRemark(linkedHashMap.get("7"));
            parkCarMonthly.setStatus("Y");
            parkCarMonthly.setCarTypeId(vo.getCarTypeId());
            parkCarMonthly.setAreaId(vo.getAreaId());
            parkCarMonthly.setAreaName(vo.getAreaName());
            parkCarMonthly.setUpdateTime(new Date());
            parkCarMonthly.setCreateUser(loginUser.getUsername());

            if (!noSameDataPlantNoList.add(parkCarMonthly.getPlateNo()) && !noSameDataParkNumberList.add(parkCarMonthly.getParkNumber())) {
                message.setPlateNo(parkCarMonthly.getPlateNo());
                message.setMessage("重复数据，重复导入");
                list.add(message);
                sameDatalist.add(parkCarMonthly);
            } else {
                noSameDataList.add(parkCarMonthly);
            }
        }
        return list;
    }

    /**
     * 检测月租车导入列表的大小
     */
    private Result<Object> importListSizeCheck(List<List<LinkedHashMap<String, String>>> list, Integer maxSize) {

        // 如果列表大小不为0
        if (list.size() != 0) {
            if (list.get(0).size() > maxSize) {
                log.error("表格中的数据最多有" + maxSize + "条");
                return Result.error("表格中的数据最多有" + maxSize + "条");
            }
            if (list.get(0).size() != 0) {
                String[] arr = new String[list.get(0).get(0).size()];
                Arrays.fill(arr, "");
                String[] arr1 = new String[list.get(0).get(0).size()];
                String[] strings = list.get(0).get(0).values().toArray(arr1);
                if (Arrays.equals(arr, strings)) {
                    log.error("文件没有数据");
                    return Result.error("文件没有数据！");
                }
            }
        } else {
            log.error("空文件");
            return Result.error("空文件");
        }
        return Result.ok();
    }

    private ParkWhiteEditList getParkWhiteEditList(ParkCarMonthly parkCarMonthly) {
        ParkWhiteEditList parkWhiteEditList = new ParkWhiteEditList();
        BeanUtils.copyProperties(parkCarMonthly, parkWhiteEditList);
        LoginUser sysUser = LoginUserUtils.getLoginUser();
        parkWhiteEditList.setId(SnowFlakeUtil.getId());
        parkWhiteEditList.setUpdateUser(sysUser.getUsername());
        parkWhiteEditList.setUpdateTime(new Date());
        return parkWhiteEditList;
    }

    private ParkSpace getParkSpace(ParkCarMonthly parkCarMonthly, LoginUser loginUser) {
        ParkSpace parkSpace = new ParkSpace();
        BeanUtils.copyProperties(parkCarMonthly, parkSpace);

        parkSpace.setAreaId(parkCarMonthly.getAreaId());
        parkSpace.setAreaName(parkCarMonthly.getAreaName());
        parkSpace.setParkStatus("0");

        parkSpace.setId(SnowFlakeUtil.getId());
        parkSpace.setCreateUser(loginUser.getUsername());
        parkSpace.setCreateTime(new Date());
        return parkSpace;
    }
}
